package com.beantools.reflect.enums;

import com.alibaba.fastjson.JSONObject;
import com.beantools.execption.ClassException;
import com.beantools.execption.PropertyException;
import com.beantools.util.ArrayUtil;

import java.lang.reflect.Field;

import static com.beantools.util.ObjectUtil.isNull;
import static java.math.BigDecimal.ROUND_CEILING;

/**
 * 这是根据枚举对象加载出当前对象的信息。
 * <p>
 * 服务端与客户端交互时，往往服务端在数据库中存在某个枚举的<code>name</code>对象，但是，客户端
 * 需要拿到该枚举的其他属性，因而，可以通过这个方法实现。
 *
 * @author baoya
 * @version 1.0
 * @since 1.1.0
 */

public class EnumObjectJson extends AbstractsEnumJson {

    /**
     * 这是加载枚举类对象，并指定哪些属性可以被加载出来
     * 如果<code>fieldNames</code>为空，或者长度为0，则返回当前类对象的所有属性
     *
     * @param obj        枚举类对象
     * @param fieldNames 调用指定的枚举类的属性
     * @return 返回枚举类
     */
    public static <T> JSONObject assignPropertyObjToJson(Object obj, String... fieldNames) throws ClassException, PropertyException {
        JSONObject jsonObject = objToJson(obj);
        if (ArrayUtil.isEmpty(fieldNames) || isNull(jsonObject)) {
            return jsonObject;
        }
        checkRemoveKey(jsonObject, fieldNames, obj.getClass());
        return jsonObject;
    }

    /**
     * 这是加载枚举类对象
     * 如果当前对象<code>obj</code>为空，则返回<code>null</code>
     *
     * @param obj 枚举类对象
     * @return 返回枚举类
     */
    public static <T> JSONObject objToJson(Object obj) throws ClassException, PropertyException {
        if (isNull(obj)) {
            return null;
        }
        Class<?> clazz = obj.getClass();
        if (!clazz.isEnum()) {
            throw new ClassException("不是枚举类", clazz);
        }
        try {
            JSONObject json = new JSONObject(ROUND_CEILING);
            // 【1】填充key值
            json.put("key", obj);
            if (obj instanceof Number) {
                int ordinal = ((Number) obj).intValue();
                Object[] values = clazz.getEnumConstants();
                if (ordinal < values.length) {
                    json = new JSONObject(ROUND_CEILING);
                    json.put("key", values[ordinal]);
                }
            }
            // 【2】填充value值
            Field[] declaredFields = obj.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                Class<?> type = declaredField.getType();
                if (type.equals(clazz)) {
                    continue;
                }
                String name = declaredField.getName();
                if (name.equals("$VALUES")) {
                    continue;
                }
                declaredField.setAccessible(true);
                Object o = declaredField.get(obj);
                json.put(name, o);
            }
            return json;
        } catch (Exception ex) {
            throw new PropertyException("转化枚举失败 : " + clazz.getName());
        }
    }


}
